From: kfraser@dhcp93.uk.xensource.com Date: Thu, 1 Jun 2006 09:34:21 +0000 (+0100) Subject: Fix MMU_NORMAL_PT_UPDATE when passed a page that is no longer of type page-table. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~15972^2~61 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=6c00bbc075e61a342450a2fd196a504224827af7;p=xen.git Fix MMU_NORMAL_PT_UPDATE when passed a page that is no longer of type page-table. Signed-off-by: Keir Fraser --- diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 622b9505dc..975c6955b5 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2213,99 +2213,88 @@ int do_mmu_update( switch ( (type_info = page->u.inuse.type_info) & PGT_type_mask ) { - case PGT_l1_page_table: - ASSERT( !shadow_mode_refcounts(d) ); - if ( likely(get_page_type( + case PGT_l1_page_table: + case PGT_l2_page_table: + case PGT_l3_page_table: + case PGT_l4_page_table: + { + ASSERT(!shadow_mode_refcounts(d)); + if ( unlikely(!get_page_type( page, type_info & (PGT_type_mask|PGT_va_mask))) ) - { - l1_pgentry_t l1e; + goto not_a_pt; - /* FIXME: doesn't work with PAE */ - l1e = l1e_from_intpte(req.val); + switch ( type_info & PGT_type_mask ) + { + case PGT_l1_page_table: + { + l1_pgentry_t l1e = l1e_from_intpte(req.val); okay = mod_l1_entry(va, l1e); if ( okay && unlikely(shadow_mode_enabled(d)) ) shadow_l1_normal_pt_update( d, req.ptr, l1e, &sh_mapcache); - put_page_type(page); } break; - case PGT_l2_page_table: - ASSERT( !shadow_mode_refcounts(d) ); - if ( likely(get_page_type( - page, type_info & (PGT_type_mask|PGT_va_mask))) ) + case PGT_l2_page_table: { - l2_pgentry_t l2e; - - /* FIXME: doesn't work with PAE */ - l2e = l2e_from_intpte(req.val); + l2_pgentry_t l2e = l2e_from_intpte(req.val); okay = mod_l2_entry( (l2_pgentry_t *)va, l2e, mfn, type_info); if ( okay && unlikely(shadow_mode_enabled(d)) ) shadow_l2_normal_pt_update( d, req.ptr, l2e, &sh_mapcache); - put_page_type(page); } break; #if CONFIG_PAGING_LEVELS >= 3 - case PGT_l3_page_table: - ASSERT( !shadow_mode_refcounts(d) ); - if ( likely(get_page_type( - page, type_info & (PGT_type_mask|PGT_va_mask))) ) + case PGT_l3_page_table: { - l3_pgentry_t l3e; - - /* FIXME: doesn't work with PAE */ - l3e = l3e_from_intpte(req.val); + l3_pgentry_t l3e = l3e_from_intpte(req.val); okay = mod_l3_entry(va, l3e, mfn, type_info); if ( okay && unlikely(shadow_mode_enabled(d)) ) shadow_l3_normal_pt_update( d, req.ptr, l3e, &sh_mapcache); - put_page_type(page); } break; #endif #if CONFIG_PAGING_LEVELS >= 4 - case PGT_l4_page_table: - ASSERT( !shadow_mode_refcounts(d) ); - if ( likely(get_page_type( - page, type_info & (PGT_type_mask|PGT_va_mask))) ) + case PGT_l4_page_table: { - l4_pgentry_t l4e; - - l4e = l4e_from_intpte(req.val); + l4_pgentry_t l4e = l4e_from_intpte(req.val); okay = mod_l4_entry(va, l4e, mfn, type_info); if ( okay && unlikely(shadow_mode_enabled(d)) ) shadow_l4_normal_pt_update( d, req.ptr, l4e, &sh_mapcache); - put_page_type(page); } break; #endif - default: - if ( likely(get_page_type(page, PGT_writable_page)) ) - { - if ( shadow_mode_enabled(d) ) - { - shadow_lock(d); + } - __mark_dirty(d, mfn); + put_page_type(page); + } + break; - if ( page_is_page_table(page) && - !page_out_of_sync(page) ) - { - shadow_mark_mfn_out_of_sync(v, gmfn, mfn); - } - } + default: + not_a_pt: + { + if ( unlikely(!get_page_type(page, PGT_writable_page)) ) + break; - *(intpte_t *)va = req.val; - okay = 1; + if ( shadow_mode_enabled(d) ) + { + shadow_lock(d); + __mark_dirty(d, mfn); + if ( page_is_page_table(page) && !page_out_of_sync(page) ) + shadow_mark_mfn_out_of_sync(v, gmfn, mfn); + } - if ( shadow_mode_enabled(d) ) - shadow_unlock(d); + *(intpte_t *)va = req.val; + okay = 1; - put_page_type(page); - } - break; + if ( shadow_mode_enabled(d) ) + shadow_unlock(d); + + put_page_type(page); + } + break; } unmap_domain_page_with_cache(va, &mapcache);